/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  FieldCollector.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/09/11
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef FIELDCOLLECTOR_H_B8F4C66F_4BC8_47D0_956C_65A9EAFAF790
#define FIELDCOLLECTOR_H_B8F4C66F_4BC8_47D0_956C_65A9EAFAF790
#include "TableCodecCommon.h"
#include "common_util.h"
#include <vector>
#include <string>

namespace qb{
	namespace proto{
		class StopCodec;
		class TableCodec;
		class SSPROTOAPI OpBitStack {
			typedef StackArray<unsigned char, 128> CharStack;
			CharStack	m_stack;
		public:
			OpBitStack(){}
			OpBitStack& operator=(const OpBitStack& op)
			{
				m_stack.Clear();
				m_stack.Add(op.m_stack.GetBuf(), op.m_stack.size());
				return *this;
			}
			void clear(){ m_stack.Clear(); }
			int  size()const{ return m_stack.size(); }
			void reserve(int capcity){
				m_stack.Reserve(capcity);
			}
			unsigned char operator[](int index)const{
				return m_stack.at(index);
			}
			unsigned char& operator[](int index){
				return m_stack.at(index);
			}
		};
		//typedef std::vector<unsigned char> OpBitmap;
		typedef OpBitStack OpBitmap;
		struct SSPROTOAPI StatValue{
			int			count;
			double		imax;
			double		imin;
			double		sum;
		public:
			StatValue() :count(0), imax(0), imin(0), sum(0){}
			double avg()const{ return count <= 0 ? 0 : (sum / count); }
			void Add(double v){
				sum += v;
				imax = count <= 0 ? v : (v > imax ? v : imax);
				imin = count <= 0 ? v : (v < imin ? v : imin);
				count++;
			}
			StatValue& operator += (double v){
				Add(v);
				return *this;
			}
			void Add(const StatValue& v);
		};
		struct SSPROTOAPI FieldStat{
			std::string		name;
			StatValue	size;
			int			type[kExpectTypeMax];		// 原始数据类型,每种类型计数
			int			encode[kEncodeTypeAuto];	// 编码类型,每种编码计数
			int			opcount[2];					// 是否使用op计数
			FieldStat(){
				opcount[0] = opcount[1] = 0;
				for (int i = 0; i < kExpectTypeMax; i++)type[i] = 0;
				for (int i = 0; i < kEncodeTypeAuto; i++)encode[i] = 0;

			}
		};
	
		class SSPROTOAPI FieldKey{
			std::string		m_str;
		public:
			FieldKey(){}
			FieldKey(int col);
			FieldKey(const std::string& str):m_str(str){}
			FieldKey(const char* str) :m_str(str){}
			FieldKey(const char* str, int len):m_str(str,len){}
			bool operator==(const FieldKey& key)const{
				return m_str == key.m_str;
			}
			bool operator==(const std::string& key)const{
				return m_str == key;
			}
			bool operator<(const FieldKey& key)const{
				return m_str < key.m_str;
			}
			const char* c_str()const{ return m_str.c_str(); }
			int size()const{ return m_str.size(); }
			operator std::string()const{ return m_str; }
		};

		//辅助key映射类
		class SSPROTOAPI SeqConvertMap
		{
			std::vector<FieldKey> m_orgin;
			std::vector<FieldKey> m_target;
			int m_lastvisit;
		public:
			SeqConvertMap();
			void Init(std::vector<FieldKey>& vecKey);
			FieldKey* ConvertFieldKey(const std::string& key);
		};

		class SSPROTOAPI FieldCollector{
			kEncodeType				m_type;			// 
			int						m_col;			// 第几列
			int						m_row;			// 共有几行
			int						m_bitwidth;
			int						m_dictindex;
			int						m_mincount;		// 开启OpBitmapFlag的最小记录个数
			std::vector<VarValue>	m_values;		// 收集到的数据
			OpBitmap				m_opbitmap;
			FieldKey				m_key;			// 键值,可以为整数或者字符串
			mutable kExpectType		m_all_type;		// 惰性计算
		public:
			FieldCollector(kEncodeType type, int col, int row);
			void SetKey(const FieldKey& key);
			const FieldKey& GetKey()const{ return m_key; }
			void SetRow(int row) { m_row = row; }
		public://收集列值
			void AddValue(int row,const VarValue& value);
			void AddDefault(int row);
			const VarValue& GetValue(int index);
			size_t GetCount()const{ return m_values.size(); }
		public:// 
			void GetStat(FieldStat& stat)const;
		public://编码到数据流中
			int GetBitWidth()const;
			bool HasDict()const{ return m_dictindex >= 0; }
			int  GetDictIndex()const;
			bool HasOpBitmap()const;
			int Encode(StopCodec* encoder,TableCodec* allocator);
		public://解码
			void SetOpBitmap(const OpBitmap& fieldOps);
			void SetBitWidth(int bitWidth){ m_bitwidth = bitWidth; }
			void SetDictIndex(int dictIndex){ m_dictindex = dictIndex; }
		public://比较值
			bool EqualValues(FieldCollector* fields)const;
		protected:
			kExpectType GetAllTypeImpl()const;
			kExpectType GetAllType()const;
			bool IsSameLength()const;
			kEncodeType DeduceStringEncodeType(OpBitmap& useOpBitmap)const;
			kEncodeType DeduceEncodeType(OpBitmap& useOpBitmap)const;
			int CalcEncodeSize(kEncodeType type, OpBitmap& useOpBitmap)const;
		};

	}//namespace base;
}//namespace ss;



#endif
